<template>
  <FormItem v-bind="formItemProps" :rules="computeRules" :disabled="inputDisabled">
    <template #default>
      <slot>
        <ElCascader
          style="width: 100%"
          :class="{ 'is-readonly': readonly }"
          :value="inputVal"
          :show-all-levels="showAllLevels"
          :separator="separator"
          :readonly="readonly"
          :options="innerOptions"
          :props="{ checkStrictly, label: labelKey, value: valueKey }"
          :disabled="inputDisabled"
          :placeholder="computePlaceholder"
          v-bind="inputProps"
          v-on="listeners"
          @input="emitInput" />
      </slot>
    </template>
    <template #error="{ error }">
      <slot name="error" :error="error"></slot>
    </template>
    <template #label>
      <slot name="label"></slot>
    </template>
  </FormItem>
</template>

<script>
  import formInput from './form-input'
  import formPick from '@/components/form/form-pick'
  import { Cascader } from 'element-ui'
  import { filterProperties, normalizeProps } from '@/util'
  import { findTreeChildren, setParent } from '@web-utils/core'
  import { cloneDeep } from '@web-utils/integrations/lodash'

  const autoBindKeys = Object.keys(Cascader.props).filter(
    key =>
      !['value', 'placeholder', 'disabled', 'options', 'showAllLevels', 'show-all-levels', 'separator'].includes(key)
  )

  export default {
    name: 'FormCascader',
    mixins: [formInput, formPick],
    props: {
      value: [String, Number],
      options: {
        type: Array,
        default: () => []
      },
      showAllLevels: Boolean,
      separator: {
        type: String,
        default: '/'
      },
      last: {
        type: Boolean,
        default: true
      },
      checkStrictly: {
        type: Boolean,
        default: true
      },
      labelKey: {
        type: String,
        default: 'label'
      },
      valueKey: {
        type: String,
        default: 'value'
      }
    },
    data() {
      return {
        innerOptions: []
      }
    },
    computed: {
      inputProps() {
        return filterProperties({ ...normalizeProps(this.$attrs), ...this.$props }, autoBindKeys)
      },
      inputVal() {
        let [parent] = findTreeChildren(this.innerOptions, node => node[this.valueKey] === this.value)
        const val = []
        while (parent) {
          val.push(parent[this.valueKey])
          parent = parent.parent
        }
        return val.reverse()
      }
    },
    watch: {
      options: {
        immediate: true,
        handler(newVal) {
          if (newVal) {
            const options = cloneDeep(newVal)
            setParent(options)
            this.innerOptions = options
          } else {
            this.innerOptions = []
          }
        }
      }
    },
    methods: {
      emitInput(val) {
        const v = this.last ? val[val.length - 1] : val
        this.$emit('input', v)
      }
    }
  }
</script>
